package collection

type linkStack[T any] struct {
	head *_node[T]
	len  int
}

func NewLinkedStack[T any]() *linkStack[T] {
	t := linkStack[T]{}
	t.head = new(_node[T])
	return &t
}
func (s *linkStack[T]) Count() int {
	return s.len
}
func (s *linkStack[T]) Peek() T {
	return s.head.next.val
}
func (s *linkStack[T]) Push(v ...T) {
	for i := 0; i < len(v); i++ {
		t := new(_node[T])
		t.val = v[i]
		t.next = s.head.next
		s.head.next = t
		s.len++
	}
}

func (s *linkStack[T]) Pop() T {
	if s.IsEmpty() {
		panic("collection is empty")
	}
	t := s.head.next.val
	s.head.next = s.head.next.next
	s.len--
	return t
}

func (s *linkStack[T]) IsEmpty() bool {
	return s.len == 0
}

func (s *linkStack[T]) Clear() {
	s.len = 0
	s.head.next = nil
}

func (s *linkStack[T]) Contain(v T, f func(a, b T) bool) bool {
	for ite := s.head.next; ite != nil; ite = ite.next {
		if f(v, ite.val) {
			return true
		}
	}
	return false
}
func (s *linkStack[T]) ToSlice() []T {
	var res = make([]T, s.len)
	i := 0
	for ite := s.head.next; ite != nil; ite = ite.next {
		res[i] = ite.val
		i++
	}
	return res
}

func (s *linkStack[T]) Copy() *linkStack[T] {
	var l = &linkStack[T]{}
	l.head = &_node[T]{}
	var vs = s.ToSlice()
	for i := len(vs) - 1; i >= 0; i-- {
		l.Push(vs[i])
	}
	return l
}
